﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace MSAS.DIP.Common
{
    public class ReadOnlyCopyFileStream : Stream
    {
        private FileStream m_read;
        private FileStream m_write;

        /// <summary>
        /// Create a new ReadOnlyCopyFileStream
        /// </summary>
        /// <param name="srcFilePath">File from which to read</param>
        /// <param name="destFileName">File to which to write</param>
        /// <exception cref="System.ArgumentException"/>
        /// <exception cref="System.ArgumentNullException"/>
        /// <exception cref="System.UnauthorizedAccessException"/>
        /// <exception cref="System.NotSupportedException"/>
        /// <exception cref="System.IO.PathTooLongException"/>
        /// <exception cref="System.IO.DirectoryNotFoundException"/>
        /// <exception cref="System.IO.FileNotFoundException"/>
        public ReadOnlyCopyFileStream(string srcFilePath, string destFileName)
        {
            try
            {
                m_read = File.OpenRead(srcFilePath);
                m_write = File.OpenWrite(destFileName);
            }
            catch
            {
                if (m_read != null)
                {
                    m_read.Dispose();
                }
                if (m_write != null)
                {
                    m_write.Dispose();
                }
                throw;
            }
        }

        public override bool CanRead
        {
            get { return m_read.CanRead; }
        }

        public override bool CanSeek
        {
            get { return m_read.CanSeek; }
        }

        public override bool CanWrite
        {
            get { return m_read.CanWrite; }
        }

        /// <summary>
        /// Clears all buffers for the streams and causes any buffered data to be written to the file system
        /// </summary>
        /// <exception cref="System.ObjectDisposedException"/>
        /// <exception cref="System.IO.IOException"/>
        public override void Flush()
        {
            m_write.Flush();
            m_read.Flush();
        }

        /// <summary>
        /// Gets the length in bytes of the read stream
        /// </summary>
        /// <exception cref="System.NotSupportedException"/>
        /// <exception cref="System.IO.IOException"/>
        public override long Length
        {
            get { return m_read.Length; }
        }

        /// <summary>
        /// Gets the current position in the read stream
        /// </summary>
        /// <exception cref="System.NotSupportedException"/>
        /// <exception cref="System.ArgumentOutOfRangeException"/>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="System.IO.EndOfStreamException"/>
        public override long Position
        {
            get
            {
                return m_read.Position;
            }
            set
            {
                throw new NotSupportedException();
            }
        }

        /// <summary>
        /// Reads a block of bytes from the stream and writes the data in a given buffer.
        /// </summary>
        /// <param name="buffer">
        ///     When this method returns, contains the specified byte array with the values
        ///     between offset and (offset + count - 1) replaced by the bytes read from the
        ///     current source.
        /// </param>
        /// <param name="offset">
        ///     The byte offset in array at which the read bytes will be placed.
        /// </param>
        /// <param name="count">
        ///     The maximum number of bytes to read.
        /// </param>
        /// <returns>
        ///     The total number of bytes read into the buffer. This might be less than the
        ///     number of bytes requested if that number of bytes are not currently available,
        ///     or zero if the end of the stream is reached.
        /// </returns>
        /// <exception cref="System.ArgumentNullException"/>
        /// <exception cref="System.ArgumentOutOfRangeException"/>
        /// <exception cref="System.NotSupportedException"/>
        /// <exception cref="System.ArgumentException"/>
        /// <exception cref="System.ObjectDisposedException"/>
        /// <exception cref="System.IO.IOException"/>
        public override int Read(byte[] buffer, int offset, int count)
        {
            int read = m_read.Read(buffer, offset, count);
            m_write.Write(buffer, offset, read);

            return read;
        }

        /// <exception cref="System.NotSupportedException"/>
        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }

        /// <exception cref="System.NotSupportedException"/>
        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }

        /// <exception cref="System.NotSupportedException"/>
        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        /// Dispose of the read and write streams
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (disposing)
            {
                m_read.Dispose();
                m_write.Dispose();
            }
        }
    }
}
